package com.jl.sms.cdma;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.jl.util.Calculator;
import com.jl.util.CodeUtil;
import com.jl.util.HexUtil;

public class BearerData implements Parameter {

	public static final byte ID = 0x08;

	private List<Parameter> subparam = new ArrayList<Parameter>();

	public BearerData(byte[] value) {
		this();
		int index = 2;
		while(index < value.length){
			addSubParameter(BearerDataParameterFactory.newInstance(value, index));
			index += value[index + 1] + 2;
		}
	}
	
	public BearerData(){
	}

	@Override
	public byte getID() {
		return ID;
	}

	@Override
	public byte[] getData() {
		byte[] data = new byte[0];
		for (Parameter one : subparam) {
			if (one == null) {
				continue;
			}
			data = HexUtil.contacByteArray(data, one.value());
		}
		return data;
	}

	@Override
	public byte[] value() {
		byte[] value = new byte[2];
		value[0] = ID;
		byte[] data = getData();
		value[1] = (byte) data.length;
		value = HexUtil.contacByteArray(value, data);
		return value;
	}
	
	@Override
	public String valueAsString() {
		return HexUtil.toHexCompact(this.value());
	}

	public BearerData addSubParameter(Parameter parameter) {
		this.subparam.add(parameter);
		return this;
	}

	public static class MessageIdentifier implements Parameter {

		public static final byte ID = 0x00;
		private int type;
		private int id;
		private boolean headerFlag;

		private byte[] allValue = new byte[5];

		public MessageIdentifier(int type, int messageID, boolean headerFlag) {
			this.type = type;
			this.id = messageID;
			this.headerFlag = headerFlag;

			allValue[0] = ID;
			allValue[1] = 0x03;
			allValue[2] = (byte) (((this.type & 0x0F) << 4) | ((this.id >> 12) & 0x0F));
			allValue[3] = (byte) ((this.id >> 4) & 0xFF);
			allValue[4] = (byte) (((this.id << 4) & 0x0F) | (this.headerFlag ? 0x08
					: 0x00));
		}

		public MessageIdentifier(int type, boolean headerFlag) {
			this(type, 0x00, headerFlag);
		}

		public MessageIdentifier(byte[] value) {
			this.allValue = value.clone();
			this.type = (allValue[2] >> 4) & 0x0F;
			this.id = (((allValue[2] << 4) | ((allValue[3] >> 4) & 0x0F)) << 8) | ((allValue[3] << 4) | ((allValue[4] >> 4) & 0x0F));
			this.headerFlag = (allValue[4] & 0x08) != 0x00;
		}

		@Override
		public byte[] value() {
			return allValue;
		}

		@Override
		public byte getID() {
			return ID;
		}

		@Override
		public byte[] getData() {
			return Arrays.copyOfRange(allValue, 2, allValue.length);
		}

		@Override
		public String valueAsString() {
			StringBuilder sb = new StringBuilder();
			sb.append("TYPE : ").append(HexUtil.toHexXX(type)).append("\n");
			sb.append("ID : ").append(HexUtil.toHex(ID, 2)).append("\n");
			sb.append("HEADER : ").append(headerFlag);
			return sb.toString();
		}

	}

	public static class DisplayMode implements Parameter {

		public static final byte ID = 0x0F;
		private byte[] allValue = new byte[3];
		private int mode;

		public DisplayMode(int mode) {
			this.mode = mode;
			allValue[0] = ID;
			allValue[1] = 1;
			allValue[2] = (byte) (mode & 0xFF);
		}

		public DisplayMode(byte[] value) {
			this.mode = value[2];
		}

		@Override
		public byte getID() {
			return ID;
		}

		@Override
		public byte[] getData() {
			return Arrays.copyOfRange(allValue, 2, allValue.length);
		}

		@Override
		public byte[] value() {
			return allValue;
		}

		@Override
		public String valueAsString() {
			String res = "";
			switch (mode) {
			case CDMA.DISPLAY_MODE_Immediate:
				res = "Immediate Display";
				break;
			case CDMA.DISPLAY_MODE_Mobile_Default:
				res = "Mobile default setting";
				break;
			case CDMA.DISPLAY_MODE_Not_Show:
				res = "Do not show to user";
				break;
			case CDMA.DISPLAY_MODE_User_Invoke:
				res = "User Invoke";
				break;
			default:
				break;
			}
			return res;
		}

	}

	/**
	 * Sub parameter UserData
	 * 
	 * @author Administrator
	 * 
	 */
	public static class UserData implements Parameter {

		public static final byte ID = 0x01;
		private int msgEncoding;
		private int msgType;
		private byte[] chars;
		/**the flag of the chars is need lsh or not*/
		private boolean packFlag;
		private byte[] allValue;

		public UserData(int msgEncoding, byte[] chars, boolean packFlag) {
			this.msgEncoding = msgEncoding;
			this.chars = chars;
			this.packFlag = packFlag;
			init();
		}

		public UserData(byte[] value) {
			this.allValue = value.clone();
			this.msgEncoding = (value[2] >> 3) & 0x1F;
			this.packFlag = true;
			byte[] temp = Arrays.copyOfRange(allValue, 2, allValue.length);
			if(packFlag){
				temp = Calculator.rsh(temp, 3);
			}else{
			}
			
			if (msgEncoding == CDMA.ENCODING_Extended_Protocol_Message) {
				msgType = CDMA.TELESERVICE_CMT_91;
			} else if (msgEncoding == CDMA.ENCODING_GSM_Data_Coding_Scheme) {
				msgType = 0x00;// FIXME : this value is not 0x00
			}
			if(msgType == 0x00){
				chars = Arrays.copyOfRange(temp, 1, temp.length);
			}else{
				chars = Arrays.copyOfRange(temp, 2, temp.length);
			}
		}

		private void init() {
			// TODO Auto-generated method stub
			if (msgEncoding == CDMA.ENCODING_Extended_Protocol_Message) {
				msgType = CDMA.TELESERVICE_CMT_91;
			} else if (msgEncoding == CDMA.ENCODING_GSM_Data_Coding_Scheme) {
				msgType = 0x00;// FIXME : this value is not 0x00
			}

			int numberFiled = 0x00;
			if (msgEncoding == CDMA.ENCODING_7bitASCII
					|| msgEncoding == CDMA.ENCODING_GSM_7bitdefaultalphabet) {
				numberFiled = chars.length / 7 * 8 + chars.length % 7;
			} else if (msgEncoding == CDMA.ENCODING_UNICODE) {
				numberFiled = chars.length / 2;
			} else {
				numberFiled = chars.length;
			}

			byte[] _bytes = null;
			if (msgType == 0x00) {
				_bytes = new byte[2];
			} else {
				_bytes = new byte[3];
				_bytes[1] = (byte) (msgType & 0xFF);
			}
			_bytes[_bytes.length - 1] = (byte) (numberFiled & 0xFF);

			_bytes = HexUtil.contacByteArray(_bytes, chars);
			if (packFlag) {
				_bytes = Calculator.lsh(_bytes, 3);
			}
			_bytes[0] |= msgEncoding << 5;

			allValue = new byte[_bytes.length + 2];
			allValue[0] = ID;
			allValue[1] = (byte) (_bytes.length & 0xFF);
			System.arraycopy(_bytes, 0, allValue, 2, _bytes.length);
		}

		@Override
		public byte getID() {
			return ID;
		}

		@Override
		public byte[] getData() {
			return Arrays.copyOfRange(allValue, 2, allValue.length);
		}

		@Override
		public byte[] value() {
			return allValue;
		}

		@Override
		public String valueAsString() {
			switch (msgEncoding) {
			case CDMA.ENCODING_7bitASCII:
			case CDMA.ENCODING_GSM_7bitdefaultalphabet:
				return CodeUtil.code7Bit(chars);
			case CDMA.ENCODING_Latin:
				return CodeUtil.codeAnsi(chars);
			case CDMA.ENCODING_UNICODE:
				return CodeUtil.codeUnicode(chars);
			default:
				return HexUtil.toHexCompact(chars);
			}
		}

	}
}
